/**
 * @(#)SystemProcessLogServiceImpl.java Aug 31, 2009
 *   
 * Copyright  (c) 2009-2010 Wilmar IT Service,  Inc.   
 * All  rights  reserved.   
 * TODO
 */

package com.wilmar.process.core.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.task.Task;

import com.wilmar.process.core.services.api.ISystemProcessLogService;
import com.wilmar.process.core.services.spi.IAttachementService;
import com.wilmar.process.dao.api.IProcessLogDAO;
import com.wilmar.process.entity.Attachement;
import com.wilmar.process.entity.InstanceOperateOpinion;
import com.wilmar.process.entity.ProcessLog;
import com.wilmar.process.entity.User;
import com.wilmar.process.entity.query.ProcessLogQueryObject;
import com.wilmar.process.entity.vo.ProcessLogVO;
import com.wilmar.process.enumerate.EnumProcessLogLevel;
import com.wilmar.process.enumerate.EnumProcessOperateOpinionType;
import com.wilmar.process.enumerate.EnumSystemQueryNameSet;
import com.wilmar.process.exception.ObjectNotFoundException;

/**
 * 系统流程日志服务实现
 * 
 * @author MaKuBEX Email:makubexnet@gmail.com
 * @version 1.0.0
 */
public class SystemProcessLogServiceImpl implements ISystemProcessLogService {
	private IProcessLogDAO processLogDAO;
	private IAttachementService attachementService;

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getDetail(java.lang.Long)
	 */
	public ProcessLog getDetail(Long id) {
		ProcessLog logEntity = this.processLogDAO.getDetail(id);
		return logEntity;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getListByProcessInstanceId(java.lang.String)
	 */
	public List<ProcessLog> getListByProcessInstanceId(
			String[] processInstanceId, EnumProcessLogLevel logLevel) {
		ProcessLogQueryObject prototype = new ProcessLogQueryObject();
		prototype.setProcessInstanceId(processInstanceId);
		prototype.setMinLogLevel(logLevel);
		List<ProcessLog> logList = this.processLogDAO
				.getListByQueryObject(prototype);
		return logList;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getListOnlyStartRecordByUser(com.wilmar.process.entity.User)
	 */
	public List<ProcessLog> getListOnlyStartRecordByUser(User user,
			ProcessLogQueryObject prototype) {
		prototype.setStartLog(true);
		List<ProcessLog> logList = this.processLogDAO
				.getListByQueryObject(prototype);
		return logList;
	}

	public IProcessLogDAO getProcessLogDAO() {
		return processLogDAO;
	}

	/**
	 * 
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#saveOperateLog
	 *      (org.jbpm.api.ProcessInstance, java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public void saveOperateLog(String processInstanceId,
			String processDefinitionName, Task taskInstance, User operator,
			InstanceOperateOpinion opinion, String outCome) {
		ProcessLog operateLog = new ProcessLog();
		operateLog.setEnterTime(taskInstance.getCreateTime());
		operateLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_FOUR);
		operateLog.setNodeDesc(taskInstance.getDescription());
		operateLog.setNodeName(taskInstance.getName());
		operateLog.setOperator(operator.getId());
		operateLog.setOperatorName(operator.getName());
		operateLog.setOpinionString(opinion.getOpinionString());
		operateLog.setOpinionType(opinion.getOpinionType());
		operateLog.setOuterSystem(operator.getOuterSystem());
		operateLog.setLeaveTime(new Date());
		operateLog.setProcessDefinitionName(processDefinitionName);
		operateLog.setProcessInstanceId(processInstanceId);
		operateLog.setExecutionId(taskInstance.getId());
		operateLog.setOutCome(outCome);
		this.saveProcessLog(operateLog);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#saveProcessLog(com.wilmar.process.entity.ProcessLog)
	 */
	public void saveProcessLog(ProcessLog aLog) {
		this.processLogDAO.save(aLog);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#saveStartLog(org.jbpm.api.ProcessDefinition,
	 *      org.jbpm.api.ProcessInstance, com.wilmar.process.entity.User)
	 */
	public void saveStartLog(ProcessDefinition processDefinition,
			String processStartNodeName, ProcessInstance processInstance,
			User starter) {
		ProcessLog startLog = new ProcessLog();
		startLog.setNodeName(processStartNodeName);
		startLog.setProcessDefinitionName(processDefinition.getName());
		startLog.setNodeDesc(processDefinition.getDescription());
		startLog.setEnterTime(new Date());
		startLog.setInstanceStarter(starter.getId());
		startLog.setOperator(starter.getId());
		startLog.setOperatorName(starter.getName());
		startLog.setOpinionType(EnumProcessOperateOpinionType.MESSAGE);
		startLog.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_FOUR);
		startLog.setProcessInstanceId(processInstance.getId());
		startLog.setOuterSystem(starter.getOuterSystem());
		startLog.setLeaveTime(new Date());
		this.saveProcessLog(startLog);
	}

	public void setProcessLogDAO(IProcessLogDAO processLogDAO) {
		this.processLogDAO = processLogDAO;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVO(java.lang.Object)
	 */
	public ProcessLogVO convertToVO(ProcessLog entity) {
		List<Attachement> attaList = this.attachementService
				.getListByBusinessKey(entity.getExecutionId());
		ProcessLogVO vo = new ProcessLogVO(entity, attaList);
		return vo;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVOList(java.util.List)
	 */
	public List<ProcessLogVO> convertToVOList(
			Collection<ProcessLog> entityCollection) {
		List<ProcessLogVO> voList = new ArrayList<ProcessLogVO>(
				entityCollection.size());
		for (ProcessLog log : entityCollection) {
			voList.add(this.convertToVO(log));
		}
		return voList;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getDetailOnlyStartRecordByProcessInstanceId(java.lang.String)
	 */
	public ProcessLog getDetailOnlyStartRecordByProcessInstanceId(
			String processInstanceId) throws ObjectNotFoundException {
		List<ProcessLog> logList = this.processLogDAO
				.getListByNamedQueryAndNamedParam(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_PROCESSLOG_GETDETAILONLYSTARTRECORDBYPROCESSINSTANCEID,
						"processInstanceId", processInstanceId);
		if (logList == null || logList.size() == 0) {
			throw new ObjectNotFoundException(
					"There is not a start log for this process instance id: "
							+ processInstanceId);
		}
		return logList.get(0);
	}

	/**
	 * @return the attachementService
	 */
	public IAttachementService getAttachementService() {
		return attachementService;
	}

	/**
	 * @param attachementService
	 *            the attachementService to set
	 */
	public void setAttachementService(IAttachementService attachementService) {
		this.attachementService = attachementService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getListRecordByUser(com.wilmar.process.entity.User,
	 *      com.wilmar.process.entity.query.ProcessLogQueryObject)
	 */
	public List<ProcessLog> getListRecordByQueryObject(
			ProcessLogQueryObject prototype) {
		List<ProcessLog> logList = this.processLogDAO
				.getListByQueryObject(prototype);
		return logList;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessLogService#getOperateLogByExecutionId(java.lang.String)
	 */
	public ProcessLog getOperateLogByExecutionId(String executionId)
			throws ObjectNotFoundException {
		ProcessLogQueryObject prototype = new ProcessLogQueryObject();
		prototype.setLogLevel(EnumProcessLogLevel.LOG_LEVEL_FOUR);
		prototype.setTaskInstanceId(executionId);
		List<ProcessLog> logList = this.processLogDAO
				.getListByQueryObject(prototype);
		if (logList == null || logList.isEmpty()) {
			throw new ObjectNotFoundException(
					"Here is no operate log for task instance : " + executionId);
		}
		return logList.get(0);
	}

}
